package com.punai.customer.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.punai.common.core.domain.TreeBo;
import com.punai.common.exception.ServiceException;
import com.punai.common.utils.SecurityUtils;
import com.punai.common.utils.StringUtils;
import com.punai.customer.domain.CusGxChapter;
import com.punai.customer.domain.contants.CusConstants;
import com.punai.customer.mapper.CusGxChapterMapper;
import com.punai.customer.mapper.CusGxFeeMapper;
import com.punai.customer.service.ICusGxChapterService;
import com.punai.standard.domain.StaGxChapter;
import com.punai.standard.mapper.StaGxChapterMapper;
import com.punai.standard.mapper.StaVersionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 工序分包费用项章节Service业务层处理
 *
 * @author zxw
 * @date 2022-12-09
 */
@Service
public class CusGxChapterServiceImpl extends ServiceImpl<CusGxChapterMapper, CusGxChapter> implements ICusGxChapterService
{
    @Autowired
    private CusGxChapterMapper dmcGxChapterMapper;
    @Autowired
    private CusGxFeeMapper cusGxFeeMapper;
    @Autowired
    private StaVersionMapper staVersionMapper;
    @Autowired
    private StaGxChapterMapper staGxChapterMapper;

    /**
     * 查询工序分包费用项章节
     *
     * @param id 工序分包费用项章节主键
     * @return 工序分包费用项章节
     */
    @Override
    public CusGxChapter selectDmcGxChapterById(String id)
    {
        return dmcGxChapterMapper.selectDmcGxChapterById(id);
    }

    /**
     * 查询工序分包费用项章节列表
     *
     * @param dmcGxChapter 工序分包费用项章节
     * @return 工序分包费用项章节
     */
    @Override
    public List<CusGxChapter> selectDmcGxChapterList(CusGxChapter dmcGxChapter)
    {
        return dmcGxChapterMapper.selectDmcGxChapterList(dmcGxChapter);
    }

    /**
     * 新增工序分包费用项章节
     *
     * @param dmcGxChapter 工序分包费用项章节
     * @return 结果
     */
    @Override
    @Transactional
    public int insertDmcGxChapter(CusGxChapter gxChapter)
    {
        Long companyId = SecurityUtils.getCompanyId();
        gxChapter.setCompanyId(companyId);
        CusGxChapter chapter = getById(gxChapter.getPid(), companyId);
        gxChapter.setSpecId(chapter.getSpecId());
        gxChapter.setPids(chapter.getPids() + "," + chapter.getId());
        Integer maxOrderNum = maxOrderNum(gxChapter.getPid(),companyId);
        gxChapter.setOrderNum(maxOrderNum + 1);
        return dmcGxChapterMapper.insert(gxChapter);
    }

    @Override
    public int updateDmcGxChapter(CusGxChapter gxChapter)
    {
        Long companyId = SecurityUtils.getCompanyId();
        // 修改只能改名称
        CusGxChapter updateEntity = new CusGxChapter();
        updateEntity.setName(gxChapter.getName());
        LambdaQueryWrapper<CusGxChapter> eq = Wrappers.<CusGxChapter>lambdaQuery()
                .eq(CusGxChapter::getCompanyId, companyId)
                .eq(CusGxChapter::getId, gxChapter.getId());
        return dmcGxChapterMapper.update(updateEntity,eq);
    }
    /**
     * 删除工序分包费用项章节信息
     *
     * @param id 工序分包费用项章节主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteDmcGxChapterById(String id)
    {
        Long companyId = SecurityUtils.getCompanyId();
        List<String> childrenIds = dmcGxChapterMapper.selectChildrenIdById(id, companyId);
        childrenIds.add(id);
        cusGxFeeMapper.updateChapterId(childrenIds,companyId,CusConstants.CHAPTER_ID_NULL);
        return dmcGxChapterMapper.deleteDmcGxChapterByIds(childrenIds,companyId);
    }

    @Override
    public List<TreeBo> treeData(Long companyId) {
        List<CusGxChapter> dmcGxChapters = dmcGxChapterMapper.selectList(
                Wrappers.<CusGxChapter>lambdaQuery()
                        .eq(CusGxChapter::getCompanyId, companyId)
        );
        List<TreeBo> convert = TreeBo.convert(dmcGxChapters);
        if (CollUtil.isNotEmpty(convert)) {
            for (TreeBo treeBo : convert) {
                List<TreeBo> children = treeBo.getChildren();
                for (TreeBo child : children) {
                    child.setFbId(child.getId());
                    setChildrenFbId(child);
                }
            }
        }
        return convert;
    }

    @Override
    public List<TreeBo> getSpecialtyList(Long companyId) {
        List<CusGxChapter> cusGxChapters = dmcGxChapterMapper.selectList(
                Wrappers.<CusGxChapter>lambdaQuery()
                        .eq(CusGxChapter::getCompanyId, companyId)
                        .eq(CusGxChapter::getPid, CusConstants.DEF_PID)
        );
        return TreeBo.sortConvert(cusGxChapters);
    }

    @Override
    public List<TreeBo> treeDataByTopId(String topId, Long companyId) {
        List<CusGxChapter> dmcGxChapters =  dmcGxChapterMapper.selectListByTopId(topId,companyId);
        List<TreeBo> convert = TreeBo.convert(dmcGxChapters);
        if (CollUtil.isNotEmpty(convert)) {
            for (TreeBo treeBo : convert) {
                List<TreeBo> children = treeBo.getChildren();
                for (TreeBo child : children) {
                    child.setFbId(child.getId());
                    setChildrenFbId(child);
                }
            }
            return convert.get(0).getChildren();
        }
        return convert;
    }

    @Override
    public StaGxChapter getStaGxChapterById(String id, String specId, Long companyId) {
        String newestId = staVersionMapper.getNewestId(companyId, CusConstants.GX_TYPE,specId);
        return staGxChapterMapper.selectStaGxChapterById(newestId,id);
    }

    @Override
    @Transactional
    public void moveTree(String type, String id, String dropId) {
        Long companyId = SecurityUtils.getCompanyId();
        if (!StrUtil.containsAny(type,"inner","before","after")) {
            throw new ServiceException("参数错误!");
        }
        CusGxChapter chapter = getById(dropId, companyId);
        CusGxChapter moveChapter = getById(id, companyId);

        if(!StringUtils.equals(moveChapter.getSpecId(),chapter.getSpecId())){
            throw new ServiceException("出现问题数据,请联系管理员!");
        }
        // 处理 移动数据之后的数据
        String targetPid = chapter.getPid();
        String movePid = moveChapter.getPid();
        boolean isProcessLastOrderNum = false;
        // 切换层级了
        boolean changeParent = false;

        if (!StrUtil.equals(targetPid,movePid)) {
            changeParent = true;
            // 发生了pid替换
            // 将之后的章节的 orderNum - 1
            orderNumProcess(companyId,movePid,moveChapter.getOrderNum(),-1);
            isProcessLastOrderNum = true;
        }
        if ( StringUtils.equals(type,"inner")) {
            // 处理后面的节点
            if (!isProcessLastOrderNum) {
                orderNumProcess(companyId,movePid,moveChapter.getOrderNum(),-1);
            }
            // 放到了谁的里面 成为了谁的孩子 会成为最后一个
            // 处理序号
            Integer targetOrderNum = maxOrderNum(chapter.getId(),companyId);
            moveChapter.setOrderNum(targetOrderNum + 1);
            String newPids = StrUtil.emptyToDefault(chapter.getPids(),"0") + "," + chapter.getId();
            String oldPids = moveChapter.getPids();
            moveChapter.setPid(chapter.getId());
            moveChapter.setPids(newPids);
            // 处理子节点的pid
            updateChapterChildrenPids(moveChapter.getId(),companyId,newPids,oldPids);
        } else if( StringUtils.equals(type,"before")) {
            if (changeParent) {
                // 在谁之前
                Integer targetOrderNum = chapter.getOrderNum();
                // 处理目标之后的序号
                orderNumProcess(companyId,targetPid,targetOrderNum,+1);
                // 处理目标序号
                chapter.setOrderNum(targetOrderNum + 1);
                // 把目标序号赋给插入进来的对象
                moveChapter.setOrderNum(targetOrderNum);
            } else {
                // 同层
                Integer targetOrderNum = chapter.getOrderNum();
                Integer orderNum = moveChapter.getOrderNum();
                int num = 1;
                // 目标序号大于 当前序号
                // 下移   中间需要 -1
                // 自身 = 目标序号 - 1

                // 如果目标序号 小于当前序号
                // 上移   中间需要 +1
                // 自身 = 目标序号
                // 目标 = 目标序号 + 1
                if (targetOrderNum > orderNum) {
                    num = -1;
                }
                if (Math.abs(targetOrderNum-orderNum) == 1) {
                    chapter.setOrderNum(orderNum);
                    moveChapter.setOrderNum(targetOrderNum);
                } else {
                    orderNumProcessStartEnd(companyId,targetPid,Math.min(targetOrderNum,orderNum),Math.max(targetOrderNum,orderNum),num);
                    if (num == 1) {
                        // 目标序号 小于 当前当前 上移
                        // 自身 = 目标序号
                        moveChapter.setOrderNum(targetOrderNum);
                        // 目标
                        chapter.setOrderNum(targetOrderNum + 1);
                    } else {
                        // 目标序号 大于 当前当前 下移
                        // 自身 = 目标序号 - 1
                        moveChapter.setOrderNum(targetOrderNum - 1);
                    }
                }
            }
        } else if( StringUtils.equals(type,"after")) {
            if (changeParent) {
                // 在谁之后
                Integer targetOrderNum = chapter.getOrderNum();
                // 处理目标之后的序号
                orderNumProcess(companyId,targetPid,targetOrderNum,+1);
                // 把目标序号赋给插入进来的对象
                moveChapter.setOrderNum(targetOrderNum + 1);
            } else {
                Integer targetOrderNum = chapter.getOrderNum();
                Integer orderNum = moveChapter.getOrderNum();
                // 之后

                // 目标序号大于 当前序号
                // 下移   中间需要 -1
                // 自身 = 目标序号
                // 目标 = 目标序号 - 1

                // 如果目标序号 小于当前序号
                // 上移   中间需要 +1
                // 自身 = 目标序号 + 1
                // 目标 = 目标序号

                int num = 1;
                if (targetOrderNum > orderNum) {
                    num = -1;
                }
                if (Math.abs(targetOrderNum-orderNum) == 1) {
                    chapter.setOrderNum(orderNum);
                    moveChapter.setOrderNum(targetOrderNum);
                } else {
                    orderNumProcessStartEnd(companyId,targetPid,Math.min(targetOrderNum,orderNum),Math.max(targetOrderNum,orderNum),num);
                    if (num == 1) {
                        // 如果目标序号 小于当前序号
                        // 自身 = 目标序号 + 1
                        moveChapter.setOrderNum(targetOrderNum + 1);
                    } else {
                        //  目标序号大于 当前序号
                        // 自身 = 目标序号
                        moveChapter.setOrderNum(targetOrderNum);
                        // 目标 = 目标序号 - 1
                        chapter.setOrderNum(targetOrderNum - 1);
                    }
                }
            }
        }
        if (changeParent) {
            if (!StrUtil.equals(type,"inner")) {
                // 处理pid pids
                String newPids = StrUtil.emptyToDefault(chapter.getPids(),"");
                String oldPids = moveChapter.getPids();
                moveChapter.setPid(chapter.getPid());
                moveChapter.setPids(newPids);
                updateChapterChildrenPids(moveChapter.getId(),companyId,newPids,oldPids);
            }
        }

        moveChapter.setSpecId(chapter.getSpecId());
        updateCusSubcontractChapter(chapter);
        updateCusSubcontractChapter(moveChapter);
    }

    private int updateCusSubcontractChapter(CusGxChapter chapter) {
        LambdaQueryWrapper<CusGxChapter> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(CusGxChapter::getCompanyId,chapter.getCompanyId());
        queryWrapper.eq(CusGxChapter::getId,chapter.getId());
        int update = dmcGxChapterMapper.update(chapter, queryWrapper);
        return update;
    }

    private void updateChapterChildrenPids(String id, Long companyId, String newPids, String oldPids) {
        List<CusGxChapter> children = dmcGxChapterMapper.selectChildrenById(id,companyId);
        if (CollUtil.isNotEmpty(children)) {
            for (CusGxChapter child : children) {
                child.setPids(child.getPids().replaceFirst(oldPids,newPids));
            }
            dmcGxChapterMapper.updateChildrenPids(children,companyId);
        }
    }

    private String getChildMaxLengthPids(String id,Long companyId) {
        return dmcGxChapterMapper.getChildMaxLengthPids(id,companyId);
    }

    private void orderNumProcessStartEnd(Long companyId, String pid, int startNum, int endNum, int num) {
        if (num == 1 || num == -1) {
            dmcGxChapterMapper.orderNumProcessStartEnd(companyId,pid,startNum,endNum,num);
        } else {
            throw new ServiceException("序号参数错误");
        }
    }

    private void orderNumProcess(Long companyId, String pid, Integer orderNum, int num) {
        if (num == 1 || num == -1) {
            dmcGxChapterMapper.orderNumProcess(companyId,pid,orderNum,num);
        } else {
            throw new ServiceException("序号参数错误");
        }
    }

    private CusGxChapter getById(String id, Long companyId) {
        return dmcGxChapterMapper.selectOne(
                Wrappers.<CusGxChapter>lambdaQuery()
                        .eq(CusGxChapter::getCompanyId, companyId)
                        .eq(CusGxChapter::getId, id)
        );
    }

    private void setChildrenFbId(TreeBo child) {
        List<TreeBo> children = child.getChildren();
        String fbId = child.getFbId();
        if (CollUtil.isNotEmpty(children)) {
            for (TreeBo treeBo : children) {
                treeBo.setFbId(fbId);
                setChildrenFbId(treeBo);
            }
        }
    }

    private Integer maxOrderNum(String pid,Long companyId) {
        return dmcGxChapterMapper.maxOrderNum(pid,companyId);
    }
}
